#include "deviceprotocol.h"
#include "edevice.h"
#include "protocol_define.h"
#include "comm/pnet103app.h"
#include <QtDebug>
#include "sys/sysapp.h"
#include <QSysInfo>
#include "comm/promonitorapp.h"
#include "pro103appprivate.h"
#include <QBitArray>
#include <QDir>
#include <QSettings>
#include "tool/toolapi.h"
#include "ipc/ipcclient.h"

DataType::DataType()
{
    m_type=0;
    m_size=0;
    m_num=0;
}

bool DataType::IsValid() const
{
    return !(m_size==0 && m_num==0);
}

uint DataType::GetLength()const
{
    if(m_type==2){
        return (m_size+7)/8 * m_num;
    }
    return m_size* m_num;
}

///////////////////////////////////////////////////////
DeviceProtocol::DeviceProtocol(EDevice *parent) :
    QObject(parent)
{
    m_device = parent;
    m_RII=0;
    m_readCatalogueCommand=0;
    isQueryingLuBo=false;
    connect(this,&DeviceProtocol::reciveAllLuBoPacket,this,&DeviceProtocol::GetLuBo);
}

void DeviceProtocol::OnTimer()
{
    QDateTime now = QDateTime::currentDateTime();
    if(!m_generalQueryTime.isValid() ||m_generalQueryTime.secsTo(now)>g_103p->m_periodGeneral){
        SendGeneralQuery();
        if(isQueryingLuBo==false){
            QueryWaveFileList();
        }

    }
}

void DeviceProtocol::QueryWaveFileList()
{
    QString ipa=m_device->m_obj->Get("ipa").toString();
    ushort ip_u=m_device->GetDevAddr(); // 43777
    ip=ip_u>>8; // ip是除后结果，ip_u是余数
    addr=ip_u;
    ip_addr=ipa.append("_").append(QString::number(addr));

    isQueryingLuBo=true;
    luBo_list.clear();
    CAsdu201 a201;
    a201.m_Addr=addr;
    QByteArray sData;
    sData.resize(0);
    a201.BuildArray(sData);
    SendAsdu(sData);
}

void DeviceProtocol::QueryChanel()
{
    m_lstQueryChannelPack.clear();
    for(int i=0;i<4;i++)
    {
        QVariantMap map;
        CAsdu21 a21;
        a21.m_Addr=addr;
        a21.m_INF=0xf1;
        a21.m_NOG=0x01;
        a21.m_DataSets.clear();
        DataSet *pDataSet=new DataSet;
        if(i<3)
        {
            pDataSet->gin.GROUP=0x1d;
            pDataSet->gin.ENTRY=0x00;
            if(i==0) pDataSet->kod=10;  // 描述
            if(i==1) pDataSet->kod=9;   // 量纲，即单位
            if(i==2) pDataSet->kod=1;   // 实际值，即系数
        }else{
            pDataSet->gin.GROUP=0x20;
            pDataSet->gin.ENTRY=0x00;
            pDataSet->kod=10;

        }
        a21.m_DataSets.append(*pDataSet);
        a21.m_RII=i;
        m_lstQueryChannelPack.append(a21);
        delete pDataSet;
    }
    QByteArray sData;
    CAsdu21 a21=m_lstQueryChannelPack.at(0);
    m_lstQueryChannelPack.pop_front();
    a21.BuildArray(sData);
    SendAsdu(sData);
}

void DeviceProtocol::ReadCatalog()
{
    if(m_readCatalogueCommand){
        return;
    }
    m_readCatalogueCommand = new ReadCatalogueCommand(this);
    m_readCatalogueCommand->DoCommand();
}

void DeviceProtocol::AddDataType(const QString& key,const DataType& dt)
{
    if(!m_mapDataType.contains(key)){
        m_mapDataType[key]=dt;
    }
}

void DeviceProtocol::ResetSignal()
{
    qDebug()<<"reset singal";
    QByteArray asdu(8,0);
    asdu[ASDU_TYPE] = TYPC_COMMAND;
    asdu[ASDU_VSQ] = VSQ_COMMON1;
    asdu[ASDU_COT] = COTC_COMMAND;
    asdu[ASDU_ADDR] = m_device->GetDevAddr();
    asdu[ASDU_FUN] = 255;
    asdu[ASDU_INF] = 19;
    asdu[ASDU20_CC] = DCO_ON;
    asdu[ASDU20_RII] = GetRIIAndInc();
    SendAsdu(asdu);
}

void DeviceProtocol::GroundingJump(ProBase::ControlType ct, CommandHandler *h)
{
    GroundJumpCommand* cc = new GroundJumpCommand(this);
    cc->Init(ct);
    cc->SetHandler(h);
    cc->DoCommand();
}

void DeviceProtocol::DoControl(DbObjectPtr obj, ProBase::ControlType ct, const QVariant &val, uint check, CommandHandler *h)
{
    ControlCommand* cc = new ControlCommand(this);
    cc->SetHandler(h);
    cc->Init(obj,ct,val,check);
    cc->DoCommand();
}

DataType DeviceProtocol::GetDataType(const QString& key)
{
    return m_mapDataType.value(key,DataType());
}

GenCommand* DeviceProtocol::GetCommand(int rii)
{
    foreach (GenCommand* cmd, findChildren<GenCommand*>()) {
        if(cmd->m_RII==rii){
            return cmd;
        }
    }
    return 0;
}

void DeviceProtocol::ReadGroup(int no, int readType, CommandHandler *h)
{
    ReadGroupValueCommand* cmd = new ReadGroupValueCommand(this);
    cmd->Init(no,readType);
    cmd->SetHandler(h);
    cmd->DoCommand();
}

void DeviceProtocol::GenWrite(const QVariantList& list,CommandHandler* h)
{
    GenWriteCommand* cmd = new GenWriteCommand(this);
    cmd->SetHandler(h);
    cmd->Init(list);
    cmd->DoCommand();
}

void DeviceProtocol::ReadRelayMeasure()
{
    foreach (int no, m_device->GetGroupNo(enumGroupTypeRelayMeasure)) {
        ReadGroupValueCommand* cmd = new ReadGroupValueCommand(this);
        cmd->Init(no,KOD_ACTUALVALUE);
        cmd->DoCommand();
    }
    m_readRelayMesureTime = QDateTime::currentDateTime();
}

void DeviceProtocol::ReadPulse()
{
    foreach (int no, m_device->GetGroupNo(enumGroupTypeYM)) {
        ReadGroupValueCommand* cmd = new ReadGroupValueCommand(this);
        cmd->Init(no,KOD_ACTUALVALUE);
        cmd->DoCommand();
    }
    m_readPulseTime = QDateTime::currentDateTime();
}

void DeviceProtocol::AnaData(const QByteArray& data)
{
    switch((uchar)data.at(0)){
    case 5:
        HandleASDU5(data);
        break;
    case 6:
        HandleASDU6(data);
        break;
    case 10:
        HandleASDU10(data);
        break;
    case 11:
        HandleASDU11(data);
        break;
    case 23:
        HandleASDU23(data);
        break;
    case 26:
        HandleASDU26(data);
        break;
    case 28:
        HandleASDU28(data);
        break;
    case 29:
        HandleASDU29(data);
        break;
    case 31:
        HandleASDU31(data);
        break;
    case 27:
        HandleASDU27(data);
        break;
    case 30:
        HandleASDU30(data);
        break;
    case 201:
    {
        QSettings *waveFileList=new QSettings("WaveFile/"+ip_addr+"/FileList.ini",QSettings::IniFormat);
        qDebug()<<ip_addr;
        waveFileList->beginGroup("List");
        CAsdu a;
        a.m_ASDUData.resize(0);
        a.SaveAsdu(data);
        if(a.m_iResult==0) return;
        CAsdu201 a201(a);
        if(a201.listNum<=0){
            isQueryingLuBo=false;
            return;//有录波文件才召
        }
        for(int i=0;i<a201.listNum;i++)
        {
            int num=a201.m_DataSets.at(i).lubo_num;
            waveFileList->setValue(QString::number(i+1),QString("%1").arg(num,5,10,QChar('0')));
        }
        waveFileList->endGroup();
        delete waveFileList;

        for(int i=0;i<a201.listNum;i++)
        {
            luBo_list.append(a201.m_DataSets.at(i).file_name);
        }
        if(luBo_list.size()>0)
        {
            emit reciveAllLuBoPacket(luBo_list.at(0));
        }
        break;
    }
    case 200:
    {
        CAsdu a;
        a.SaveAsdu(data);
        if(a.m_iResult==0)return;
        CAsdu200 a200(a);
        a200_list.append(a200);
        if(a200.followTag==0)//传输完成
        {
            QTextCodec *BianMa = QTextCodec::codecForName("GBK");
            QByteArray file_name=a200_list.at(0).file_name;
            QString qFile_name=BianMa->toUnicode(file_name);
            QFile file("WaveFile/"+ip_addr+"/"+qFile_name+".dat");
            file.open(QIODevice::WriteOnly | QIODevice::Append);
            QTextStream in(&file);
            in.setCodec(QTextCodec::codecForName("UTF-8"));
            for(CAsdu200 a:a200_list)
            {
                file.write(a.all_packet,a.all_packet.size());
            }
            file.close();
            a200_list.clear();

            /*召唤下个录波文件*/
            for(int i=0;i<luBo_list.size();i++)
            {
                if(file_name==luBo_list.at(i))
                {
                    if(i+1<luBo_list.size()){
                        emit reciveAllLuBoPacket(luBo_list.at(i+1));
                    }else{
                        isQueryingLuBo=false;//召唤结束将标志位重置
                        QueryChanel();
                    }
                }
            }
        }

    }
        break;
    }
}

void DeviceProtocol::GetLuBo(const QByteArray& file_name)
{
    QTextCodec *BianMa = QTextCodec::codecForName("GBK");
    QString qFile_name=BianMa->toUnicode(file_name);
    QString path_name="WaveFile/"+ip_addr;
    QDir* dir=new QDir();
    dir->mkpath(path_name);
    QFile file("WaveFile/"+ip_addr+"/"+qFile_name+".dat");
    if(file.exists())
    {
        for(int i=0;i<luBo_list.size();i++)
        {
            if(file_name==luBo_list.at(i))
            {
                if(i+1<luBo_list.size()){
                    emit reciveAllLuBoPacket(luBo_list.at(i+1));
                }else{
                    isQueryingLuBo=false;//召唤结束将标志位重置
                }
            }
        }
        return;
    }
    CAsdu200 a200;
    a200.file_name=file_name;
    QByteArray sData;
    a200.BuildArray(sData);
    SendAsdu(sData);
}

uchar DeviceProtocol::GetRIIAndInc()
{
    uchar rii = m_RII;
    IncRII();
    return rii;
}

void DeviceProtocol::IncRII()
{
    if(m_RII==255){
        m_RII=0;
    }
    else{
        m_RII++;
    }
}


void DeviceProtocol::SendGeneralQuery()
{
    QByteArray asdu;
    asdu.resize(7);
    asdu[0]=0x07;
    asdu[1]=0x81;
    asdu[2]=0x09;
    asdu[3]=(uchar)m_device->GetDevAddr();
    asdu[4]=0xff;
    asdu[5]=0x00;
    asdu[6]=0xff;
    SendAsdu(asdu);

    ProMonitorApp::GetInstance()
            ->AddMonitor(ProIEC103,
                         MsgInfo,
                         m_device->GetAddrString(),
                         "发送总查询");

    m_generalQueryTime = QDateTime::currentDateTime();
}


void DeviceProtocol::GenDataHandle(const QByteArray& data,int cot)
{
    ProMonitorApp* mon = ProMonitorApp::GetInstance();
    uchar byGroup = data[GENDATAREC_GIN];//0
    uchar byInf = data[GENDATAREC_GIN+1];
    uchar kod = data[GENDATAREC_KOD];//2
    uchar byType = data[GENDATAREC_GDD];//3,这个是gdd中的第一个，也就是数据类型
    uchar byNum = data[GENDATAREC_GDD + GDDTYPE_NUM];//3+2，gdd中的数据数目
    uchar bySize = data[GENDATAREC_GDD + GDDTYPE_SIZ];//3+1，gdd中的数据宽度
    uchar* GID = (uchar*)data.data()+GENDATAREC_GID;//6，指向gid
    QString key = QString("GIN_%1_%2")
            .arg(byGroup)
            .arg(byInf);
    MeasPointInfo* mpi = m_device->GetMeasPointInfo(key);
    if(mpi&&byGroup==0x04){
        qDebug()<<"debug event"<<key;
        mpi->SetValue(1,true);
    }

    switch (byGroup) {
    case 0x06://保护测量
    case 0x0a://遥脉（电量）
    {
        if(byType == 3 && bySize == 4 && byNum == 1){
            uint dwVal = ToolByteToNumber<uint>(GID);
            if(mpi){
                mpi->SetValue(dwVal,false);
            }
            mon->AddMonitor(ProIEC103,
                            MsgInfo,
                            m_device->GetAddrString(),
                            QString("遥脉:%1,值：%2")
                            .arg(key)
                            .arg(dwVal));
        }else if(byType ==6 && bySize == 4 && byNum == 1){
            float fVal= ToolByteToNumber<float>(&GID[0]);
            if(mpi){
                mpi->SetValue(fVal,false);
            }
            mon->AddMonitor(ProIEC103,
                            MsgInfo,
                            m_device->GetAddrString(),
                            QString("遥脉:%1,值：%2")
                            .arg(key)
                            .arg(fVal));
        }
        break;
    }
    case 0x07://遥测
    {
        if(kod!=KOD_ACTUALVALUE){
            return;
        }

        //带品质描述的被测值,循环上送的遥测
        if(byType == 12 && bySize == 2 && byNum == 1 && data.size() >= 8 )
        {
            ushort code= GID[1]<<8|GID[0];
            ushort nVal=code&0x1FFF;
            double cc=1;
            if((code>>12)&0x01)
            {
                nVal=nVal<<3;
                nVal=~nVal+1;
                nVal=nVal>>3;
                cc*=-1;
            }
            double fVal = cc*nVal*1.2/4095;
            if(mpi){
                mpi->SetValue(cc*nVal);
            }
            mon->AddMonitor(ProIEC103,
                            MsgInfo,
                            m_device->GetAddrString(),
                            QString("遥测:%1,值：%2,码值：%3")
                            .arg(key)
                            .arg(fVal)
                            .arg(cc*nVal));
        }
        //ieee标准754短实数
        else if((byType== 7 || byType == 6)&& bySize == 4 && byNum == 1 && data.size() >= 10 )
        {
            float fVal= ToolByteToNumber<float>(&GID[0]);
            if(mpi){
                mpi->SetValue(fVal);
            }
            mon->AddMonitor(ProIEC103,
                            MsgInfo,
                            m_device->GetAddrString(),
                            QString("遥测:%1,值：%2")
                            .arg(key)
                            .arg(fVal)
                            );
        }

        else if(byType==3 && byNum==1 ){
            double fVal=0;
            if(bySize==2 && data.size()>=6 ){
                fVal =  ToolByteToNumber<ushort>(&GID[0]);
            }
            else if(bySize==4 && data.size()>=8 ){
                fVal = ToolByteToNumber<uint>(&GID[0]);
            }
            else{
                return;
            }
            if(mpi){
                mpi->SetValue(fVal);
            }
            mon->AddMonitor(ProIEC103,
                            MsgInfo,
                            m_device->GetAddrString(),
                            QString("遥测:%1,值：%2")
                            .arg(key)
                            .arg(fVal)
                            );
        }
    }
        break;
    case 0x08://遥信，带SOE
    case 0x09://遥信，不带SOE
    case 0x04://动作元件
    case 0x05://告警
    case 0x0e://软压板
    {
        if(kod!=KOD_ACTUALVALUE){
            return;
        }
        //qDebug()<<"遥信" ;
        if( ( byType == 19 && data.size() >= 16 && bySize == 10  )
                || ( byType == 18 && data.size() >= 12 && bySize == 6  )
                || ( byType == 203 && data.size() >= 15 && bySize == 9  )
                || ( byType == 204 && data.size() >= 19 && bySize == 13  )
                || ( byType == 3 && data.size() >= 7 && bySize == 1  )
                || ( byType == 9 && data.size() >= 7 && bySize == 1  ) ) {

            uchar byVal = GID[0] & 0x03;
            uchar val=0;
            QDateTime dt;
            if(byType != 3){
                if(byVal == 2) {
                    val = 1;
                }
                else if(byVal == 1) {
                    val = 0;
                }
                else {
                    mon->AddMonitor(ProIEC103,
                                    MsgError,
                                    m_device->GetAddrString(),
                                    QString("遥信:%1,值：%2，错误,类型:%3")
                                    .arg(key)
                                    .arg(byVal)
                                    .arg(byType)
                                    );
                    return;
                }
            }
            else {
                if(byVal != 0 && byVal != 1) {
                    mon->AddMonitor(ProIEC103,
                                    MsgError,
                                    m_device->GetAddrString(),
                                    QString("遥信:%1,值：%2，错误,类型:%3")
                                    .arg(key)
                                    .arg(byVal)
                                    .arg(byType)
                                    );
                    return;
                }
                val = byVal;
            }
            if( byType == 19 || byType == 18 ){
                uchar* pTime;
                if(byType == 19) {
                    pTime = &GID[5];
                }
                else pTime = &GID[1];
                uchar hour = pTime[SHORTTIME_HOUR];
                uchar minute = pTime[SHORTTIME_MIN];
                ushort msec = ToolByteToNumber<ushort>(&pTime[SHORTTIME_MSEC]);
                QTime t(hour,minute);
                t = t.addMSecs(msec);
                QDate d = QDate::currentDate();
                dt = QDateTime(d,t);
            }
            else if( byType == 204 || byType == 203){
                uchar* pTime;
                if(byType == 204) {
                    pTime = &GID[5];
                }
                else pTime = &GID[1];
                uchar year = pTime[LONGTIME_YEAR];
                uchar month = pTime[LONGTIME_MON];
                uchar day = pTime[LONGTIME_DAY];
                uchar hour = pTime[LONGTIME_HOUR];
                uchar minute = pTime[LONGTIME_MIN];
                ushort ms = ToolByteToNumber<ushort>(&pTime[LONGTIME_MSEC]);
                QDate d(year,month,day);
                QTime t(hour,minute);
                t=t.addMSecs(ms);
                dt = QDateTime(d,t);
            }
            bool change = (cot==1);
            //带时标的遥信的处理
            if(mpi){
                mpi->SetValue(val,change,dt);
            }
            mon->AddMonitor(ProIEC103,
                            MsgInfo,
                            m_device->GetAddrString(),
                            QString("遥信:%1,值：%2,时间：%3,原因:%4")
                            .arg(key)
                            .arg(val)
                            .arg(dt.toString("yyyy-MM-dd hh:mm:ss.zzz"))
                            .arg(cot));
        }
        break;
    default:
            break;
        }
    }
}

void DeviceProtocol::RecvGenData(const QByteArray &data, int num, int cot)
{

    if(IpcClient::GetInstance()->IsSimu()){
        return;
    }
    ushort wLen = 0;
    uchar* pHead = (uchar* )data.data();
    for(uchar i = 0; i<num; i++){
        uchar* pCurRec = (uchar* )pHead;
        ushort wDataSize;
        if(pCurRec[GENDATAREC_GDD] == 2)// 成组位串
            wDataSize = ((pCurRec[GENDATAREC_GDD+GDDTYPE_SIZ]+7)/8) * pCurRec[GENDATAREC_GDD+GDDTYPE_NUM] + 6;
        else wDataSize = pCurRec[GENDATAREC_GDD+GDDTYPE_SIZ] * pCurRec[GENDATAREC_GDD+GDDTYPE_NUM] + 6;
        pHead += wDataSize;
        wLen += wDataSize;
        if(wLen > data.size()){
            return;
        }
        QByteArray ba(wDataSize,0);
        memcpy(ba.data(), pCurRec, wDataSize);
        GenDataHandle(ba,cot);
    }
}

void DeviceProtocol::SendAsdu21(const QByteArray& data)
{
    QByteArray asdu(4,0);
    asdu[ASDU_TYPE] = (char) TYPC_GRC_COMMAND;
    asdu[ASDU_VSQ] = (char) VSQ_COMMON1;
    asdu[ASDU_COT] = (char) COTC_GRC_READ;
    asdu[ASDU_ADDR] = (uchar)(m_device->GetDevAddr());
    asdu+= data;
    SendAsdu(asdu);
}

void DeviceProtocol::SendAsdu(const QByteArray& data)
{
    if(ProMonitorApp::GetInstance()->HasMonitor()){
        ProMonitorApp::GetInstance()
                ->AddMonitor(ProIEC103,
                             MsgSend,
                             m_device->GetAddrString(),
                             QString(),
                             data);
    }
    PNet103App::GetInstance()
            ->SendAppData(m_device->GetStationAddr(),
                          m_device->GetDevAddr(),
                          data);
}

void DeviceProtocol::SendAsdu10(const QByteArray& data)
{
    QByteArray asdu(4,0);
    asdu[ASDU_TYPE] = (char) TYPC_GRC_DATA;
    asdu[ASDU_VSQ] = (char) VSQ_COMMON1;
    asdu[ASDU_COT] = (char) COTC_GRC_WRITE;
    asdu[ASDU_ADDR] = (uchar)(m_device->GetDevAddr());
    asdu+= data;
    SendAsdu(asdu);
}

QByteArray DeviceProtocol::ValueToGDD(const DataType &dat, const QString &key, const QVariant &v)
{
    uint len = dat.GetLength();
    QByteArray ba(len+6,0);
    uchar groupno = key.section("_",1,1).toUInt();
    uchar inf = key.section("_",2,2).toUInt();
    ba[GENDATAREC_GIN] = groupno;
    ba[GENDATAREC_GIN+1] = inf;
    ba[GENDATAREC_KOD] = KOD_ACTUALVALUE;
    ba[GENDATAREC_GDD] = dat.m_type;
    ba[GENDATAREC_GDD+1] = dat.m_size;
    ba[GENDATAREC_GDD+2] = dat.m_num;
    uchar* buf = (uchar*)ba.data()+6;
    switch (dat.m_type) {
    case 1:
    {
        QByteArray cstring = g_103p->m_gbk->fromUnicode(v.toString());
        memcpy(buf,cstring.data(),qMin((int)dat.m_size,cstring.length()));
    }
        break;
    case 2:
    {
        QBitArray ba = v.toBitArray();
        for(int i=0;i<dat.m_size;i++){
            int byte = i/8;
            int bit = i%8;
            uchar& bits = buf[byte];
            bool val = ba.testBit(i);
            if(val){
                bits |= (i<<bit);
            }
        }
    }
        break;
    case 3:
    {
        QVariantList list;
        if(v.type() == QVariant::List){
            list = v.toList();
        }
        else{
            list += v.toUInt();
        }
        uchar* p = buf;
        for(int i=0;i<dat.m_num;i++,p+=dat.m_size){
            if(i>=list.count()){
                break;
            }
            uint val=list.at(i).toUInt();
            if(dat.m_size==1){
                uchar v = val;
                ToolNumberToByte(p,v);
            }
            else if( dat.m_size ==2){
                ushort v = val;
                ToolNumberToByte(p,v);
            }
            else if( dat.m_size == 4){
                uint v = val;
                ToolNumberToByte(p,v);
            }
        }
    }
        break;
    case 4:
    {
        QVariantList list;
        if(v.type() == QVariant::List){
            list = v.toList();
        }
        else{
            list += v.toInt();
        }
        uchar* p = buf;
        for(int i=0;i<dat.m_num;i++,p+=dat.m_size){
            if(i>=list.count()){
                break;
            }
            int val=list.at(i).toInt();
            if( dat.m_size ==1){
                char v = val;
                ToolNumberToByte(p,v);
            }
            else if( dat.m_size ==2){
                short v = val;
                ToolNumberToByte(p,v);
            }
            else if( dat.m_size ==4){
                int v = val;
                ToolNumberToByte(p,v);
            }
        }
    }
        break;
    case 6:
    case 7:
    {
        QVariantList list;
        if(v.type() == QVariant::List){
            list = v.toList();
        }
        else{
            list += v.toFloat();
        }
        uchar* p = buf;
        for(int i=0;i<dat.m_num;i++,p+=dat.m_size){
            if(i>=list.count()){
                break;
            }
            float val=list.at(i).toFloat();
            if(dat.m_size==4){
                float v = val;
                ToolNumberToByte(p,v);
            }
        }
    }
        break;
    case 9:
        if(v.toInt()==1){
            ba[6]=0x01;
        }else if(v.toInt()==2){
            ba[6]=0x02;
        }
        break;
    default:
        qDebug()<<"未处理类型："<<dat.m_type<<",num:"<<dat.m_num
               <<",size:"<<dat.m_size;
        break;
    }
    qDebug()<<"ba"<<ba.toHex();
    return ba;
}

QVariant DeviceProtocol::GDDValue(uchar* buf,int type,int size,int num)
{
    switch (type) {
    case 1:
    {
        QByteArray ba(size,0);
        memcpy(ba.data(),buf,size);
        return g_103p->m_gbk->toUnicode(ba);
    }
        break;
    case 2:
    {
        QBitArray ba(size);
        for(int i=0;i<size;i++){
            int byte = i/8;
            int bit = i%8;
            uchar bits = buf[byte];
            bool val = (bits>>bit)!=0;
            ba.setBit(i,val);
        }
        return ba;
    }
        break;
    case 3:
    {
        QVariantList list;
        uchar* p = buf;
        for(int i=0;i<num;i++,p+=size){
            uint val=0;
            if(size==1){
                val = (uchar)p[0];
            }
            else if(size==2){
                val = ToolByteToNumber<ushort>(p);
            }
            else if(size==4){
                val = ToolByteToNumber<uint>(p);
            }
            list.append(val);
        }
        if(num==1){
            return list[0];
        }
        else{
            return list;
        }
    }
        break;
    case 4:
    {
        QVariantList list;
        uchar* p = buf;
        for(int i=0;i<num;i++,p+=size){
            int val=0;
            if(size==1){
                val = (char)p[0];
            }
            else if(size==2){
                val = ToolByteToNumber<short>(p);
            }
            else if(size==4){
                val = ToolByteToNumber<int>(p);
            }
            list.append(val);
        }
        if(num==1){
            return list[0];
        }
        else{
            return list;
        }
    }
        break;
    case 6:
    case 7:
    {
        QVariantList list;
        uchar* p = buf;
        for(int i=0;i<num;i++,p+=size){
            float val=0;
            if(size==4){
                val = ToolByteToNumber<float>(p);
            }
            list.append(val);
        }
        if(num==1){
            return list[0];
        }
        else{
            return list;
        }
    }
        break;
    case 9:
        return buf[0];
        break;
    default:
        qDebug()<<"未处理类型："<<type<<",num:"<<num;
        break;
    }
    return QVariant();
}

ushort DeviceProtocol::CalcuGrcDataLen(uchar* pgd, ushort wCount)
{
    if(wCount<4) return 0;
    ushort wLen = 4;
    uchar* pHead = (uchar* )pgd;
    pHead += 4;
    uchar byNum = pgd[GENDATACOM_NGD] & 0x3f;
    if(byNum > 0){
        for(quint32 i=0; i<byNum; i++){
            if((wLen + GENDATAREC_SIZE) > wCount){
                pgd[GENDATACOM_NGD] = 0;
                wLen = 4;
                break;
            }
            //SGenDataRec *pgdr = (SGenDataRec *)pHead;
            if(pHead[GENDATAREC_GDD] == 2){	// 成组位串
                wLen += 6+((pHead[GENDATAREC_GDD + GDDTYPE_SIZ]+7)/8)*pHead[GENDATAREC_GDD + GDDTYPE_NUM];
                pHead += 6+((pHead[GENDATAREC_GDD + GDDTYPE_SIZ]+7)/8)*pHead[GENDATAREC_GDD + GDDTYPE_NUM];
            }
            else {
                wLen += 6+pHead[GENDATAREC_GDD + GDDTYPE_SIZ]*pHead[GENDATAREC_GDD + GDDTYPE_NUM];
                pHead += 6+pHead[GENDATAREC_GDD + GDDTYPE_SIZ]*pHead[GENDATAREC_GDD + GDDTYPE_NUM];
            }
            if(wLen>wCount) {
                pgd[GENDATACOM_NGD] = 0;
                wLen = 4;
                break;
            }
        }
    }
    return wLen;
}

void DeviceProtocol::HandleASDU10(const QByteArray& data)
{
    if(data.size() <= 8) return;
    //单独处理通道信息
    if(data[8]==0x1d||data[8]==0x20)
    {
        HandleQueryChannel(data);
        return;
    }

    ushort wLen = data.size()-4;
    uchar* pData = (uchar*)data.data();
    uchar* pDataCom = (uchar* )(pData+4);
    ushort wCalLen = CalcuGrcDataLen(pDataCom, wLen);
    if(wCalLen < 4) return;

    uchar byCot = pData[ASDU_COT];//2
    uchar byRII = pData[ASDU21_RII];//6
    uchar byNum = pDataCom[GENDATACOM_NGD] & 0x3f;//3
    if(byCot == COT_SPONTANEOUS || byCot == COT_CYCLIC || byCot == COT_GI || byCot == COT_TELECONTROL){
        QByteArray ba(wCalLen-4,0);
        memcpy(ba.data(),pDataCom+4,ba.size());
        RecvGenData(ba,byNum,byCot);
    }
    else {
        GenCommand* cmd = GetCommand(byRII);
        if(!cmd){
            return;
        }
        QByteArray ba(wCalLen,0);
        memcpy(ba.data(),pDataCom,wCalLen);
        cmd->RecvData(ba,byCot);
    }
}

void DeviceProtocol::HandleQueryChannel(const QByteArray& data)
{
    if(IpcClient::GetInstance()->IsSimu()){
        return;
    }
    CAsdu a;
    a.m_ASDUData.resize(0);
    a.SaveAsdu(data);
    CAsdu10 a10(a);
    a10.ExplainAsdu();
    QTextCodec *BianMa = QTextCodec::codecForName("GBK");
    if(a10.m_RII<3)//模拟信道
    {
        QSettings *moni=new QSettings("Device_Info/WaveChannel/"+ip_addr+".ini",QSettings::IniFormat);
        QString name=m_device->m_obj->Get("name").toString();
        moni->setIniCodec("GBK");
        moni->setValue("/Device/ID",QString::number(a10.m_Addr));
        moni->setValue("/Device/NAME",name);
        moni->beginGroup("ANALOG_CHANNEL");
        for(int i=0;i<a10.m_DataSets.size();i++)
        {
            QString key=QString::number(a10.m_DataSets.at(i).gin.ENTRY);
            if(a10.m_RII==0)//通道描述
            {
                QString description=BianMa->toUnicode(a10.m_DataSets.at(i).gid);
                moni->setValue(key,description);
            }else if(a10.m_RII==1){ //量纲
                QString formalValue=moni->value(key).toString();
                QString newValue=formalValue.append(",").append(BianMa->toUnicode(a10.m_DataSets.at(i).gid));
                moni->setValue(key,newValue);
            }else if(a10.m_RII==2){//实际值，系数
                QString formalValue=moni->value(key).toString();
                uchar* GID = (uchar*)a10.m_DataSets.at(i).gid.data();
                float fVal= ToolByteToNumber<float>(&GID[0]); // 将byte数组解析成具体的浮点数
                QString newValue=formalValue+" "+QString("%1").arg(fVal);
                moni->setValue(key,QVariant(newValue));
            }
        }
        int num=moni->childKeys().size();
        moni->endGroup();
        moni->setValue("/Device/ANALOG_CHANNEL",num);
        delete moni;
    }
    else//数字信道,只召唤描述
    {
        QSettings *shuzi=new QSettings("Device_Info/WaveChannel/"+ip_addr+".ini",QSettings::IniFormat);
        shuzi->setIniCodec("GBK");
        shuzi->beginGroup("DIGIT_CHANNEL");
        for(int i=0;i<a10.m_DataSets.size();i++)
        {
            QString key=QString::number(a10.m_DataSets.at(i).gin.ENTRY);
            QString description=BianMa->toUnicode(a10.m_DataSets.at(i).gid);
            shuzi->setValue(key,description);
        }
        int num=shuzi->childKeys().size();
        shuzi->endGroup();
        shuzi->setValue("/Device/DIGIT_CHANNEL",num);
        QDateTime current_date_time =QDateTime::currentDateTime();
        QString current_date =current_date_time.toString("yyyy.MM.dd hh:mm:ss");
        shuzi->setValue("/Device/CREATE_TIME",current_date);
        delete shuzi;
    }
    if(!m_lstQueryChannelPack.isEmpty()){
        CAsdu21 a21=m_lstQueryChannelPack.at(0);
        m_lstQueryChannelPack.pop_front();
        QByteArray sData;
        a21.BuildArray(sData);
        SendAsdu(sData);
    }
}

void DeviceProtocol::HandleYXWithSOE(const QByteArray &data)
{
    if(IpcClient::GetInstance()->IsSimu()){
        return;
    }
    ProMonitorApp* mon = ProMonitorApp::GetInstance();
    CAsdu a;
    a.m_ASDUData.clear();
    a.SaveAsdu(data);
    CAsdu10 a10(a);
    a10.ExplainAsdu();
    for(int i=0;i!=a10.m_NGD.byte;i++)
    {
        DataSet ds=a10.m_DataSets.at(i);
        uchar val=ds.gid.at(0);
        QString key = QString("GIN_%1_%2")
                .arg(ds.gin.GROUP)
                .arg(ds.gin.ENTRY);
        MeasPointInfo* mpi = m_device->GetMeasPointInfo(key);
        DataSet ds_time=a10.m_DataSets.at(i+1);
        QByteArray gid_time=ds_time.gid;
        uchar* pTime=(uchar*)gid_time.data()+1;
        ushort ms=pTime[1]<<8 | pTime[0];
        uchar minute=pTime[2];
        uchar hour=pTime[3];
        QDate current_date = QDate::currentDate();
        uchar day=current_date.day();
        uchar month=current_date.month();
        uchar year=current_date.year()+1792;
        QDate d(year,month,day);
        QTime t(hour,minute);
        t=t.addMSecs(ms);
        QDateTime dt=QDateTime(d,t);
        if(mpi){
            mpi->SetValue(val,true,dt);
            mon->AddMonitor(ProIEC103,
                            MsgInfo,
                            m_device->GetAddrString(),
                            QString("遥信:%1,值：%2,时间：%3,原因:%4")
                            .arg(key)
                            .arg(val)
                            .arg(dt.toString("yyyy-MM-dd hh:mm:ss.zzz"))
                            .arg(1));
        }
        i=i+1;
        delete mpi;
    }
}

void DeviceProtocol::HandleEvent(const QByteArray& data)
{
    if(IpcClient::GetInstance()->IsSimu()){
        return;
    }
    CAsdu a;
    a.m_ASDUData.resize(0);
    a.SaveAsdu(data);
    if(a.m_iResult==0) return;
    CAsdu10Link a10Link(a);
    ushort ip_u=m_device->GetDevAddr();
    ip=ip_u>>8;
    addr=ip_u;
    ip_addr=m_device->m_obj->Get("ipa").toString();
    ip_addr.append("_").append(QString::number(addr));
    QList<ASdu10LinkDataSet> dList=a10Link.m_DataSet;
    ASdu10LinkDataSet d;
    if(dList.size()>0){
        d=dList.at(2);
        QByteArray event_num=d.gid;
        QFile file("WaveFile\\"+ip_addr+"\\"+event_num.toHex()+".txt");
        file.open(QIODevice::WriteOnly | QIODevice::Append);
        QTextStream in(&file);
        in.setCodec(QTextCodec::codecForName("UTF-8"));
        for(int i=6;i<dList.size();){
            QString description=QString::fromLocal8Bit(dList.at(i).gid);
            if(i+2<dList.size()){
                in<<description<<"--"<<QString("%1").arg(dList.at(i+2).gid.toFloat());
            }
            i=i+3;
        }
        file.close();
    }
}

void DeviceProtocol::HandleASDU5(const QByteArray& data)
{
    Q_UNUSED(data);
}

void DeviceProtocol::HandleASDU6(const QByteArray& data)
{
    Q_UNUSED(data);
}

void DeviceProtocol::HandleASDU11(const QByteArray& data)
{
    Q_UNUSED(data);
}

void DeviceProtocol::HandleASDU23(const QByteArray& data)
{
    Q_UNUSED(data);
}

void DeviceProtocol::HandleASDU26(const QByteArray& data)
{
    Q_UNUSED(data);
}


void DeviceProtocol::HandleASDU27(const QByteArray& data)
{
    Q_UNUSED(data);
}


void DeviceProtocol::HandleASDU28(const QByteArray& data)
{
    Q_UNUSED(data);
}


void DeviceProtocol::HandleASDU29(const QByteArray& data)
{
    Q_UNUSED(data);
}


void DeviceProtocol::HandleASDU30(const QByteArray& data)
{
    Q_UNUSED(data);
}


void DeviceProtocol::HandleASDU31(const QByteArray& data)
{
    Q_UNUSED(data);
}


void DeviceProtocol::HandleASDU229(const QByteArray& data)
{
    Q_UNUSED(data);
}
